/**********************************************************************************
 *  jcw - this is a environment for solving japan crosswords by users on computer *
 *  Copyright (C) 2008 by pluton <plutonpluton@mail.ru>                           *
 *                                                                                *
 *  This program is free software; you can redistribute it and/or modify          *
 *  it under the terms of the GNU General Public License as published by          *
 *  the Free Software Foundation; either version 2 of the License, or             *
 *  (at your option) any later version.                                           *
 *                                                                                *
 *  This program is distributed in the hope that it will be useful,               *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of                *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                 *
 *  GNU General Public License for more details.                                  *
 *                                                                                *
 *  You should have received a copy of the GNU General Public License along       *
 *  with this program; if not, write to the Free Software Foundation, Inc.,       *
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.                   *
 *********************************************************************************/

#include "colorcw.h"

//macro, which sets error flag
#define setDeleting \
	{ \
		needDelete = true; \
		return; \
	}

//check ok flag
#define checkOk \
	if (!ok) \
		setDeleting;

ColorCW::ColorCW(QTime* time, QWidget* parent, Qt::WindowFlags f)
	: RectCrossword(CWType::Color, time, parent, f)
{
	mode = CWType::SolvingCrossword;
}

void ColorCW::init(const QDomElement& root)
{
	QDomElement domElem = root.toElement();
	name = domElem.attribute("name");
	author = domElem.attribute("author");
	date = domElem.attribute("date");
	bool ok;
	QString ver = domElem.attribute("ver");
	numCorrections = domElem.attribute("corr", "0").toUInt(&ok);
	checkOk;
	if (this->time != NULL)
	{
		quint32 solvSec = domElem.attribute("time", "0").toUInt(&ok);
		checkOk;
		this->time->setHMS(solvSec / 3600, solvSec / 60 % 60, solvSec % 60);
	}

	quint16 i, j, k;
	QStringList list;
	QStringList list2;
	QDomNodeList nodes;

	/* if color map exists, let's fill the array*/
	nodes = domElem.elementsByTagName("colormap");
	if (!nodes.isEmpty())
	{
		domElem = nodes.item(0).toElement();
		if (!domElem.isNull())
		{
			list = domElem.text().split(';', QString::SkipEmptyParts);
			colorMap = new ColorMap [list.size()];
			colorMapCount = list.size();
			for (i = 0; i < list.size(); i++)
			{
				list2 = list.at(i).split(',', QString::SkipEmptyParts);
				if (list2.size() != 3)
					setDeleting;
				colorMap[i].red = list2.at(0).toInt(&ok);
				checkOk;
				colorMap[i].green = list2.at(1).toInt(&ok);
				checkOk;
				colorMap[i].blue = list2.at(2).toInt(&ok);
				checkOk;
				//emit addColor(QColor(colorMap[i].red, colorMap[i].green, colorMap[i].blue));
			}
		}
	}
	else
		setDeleting;

	domElem = root.toElement();

	/* let's find and read top header */
	nodes = domElem.elementsByTagName("topheader");
	if (ver == "0.2")
	{
		if (!nodes.isEmpty())
			domElem = nodes.item(0).toElement();
		else
			setDeleting;

		nodes = domElem.elementsByTagName("values");
	}
	if (!nodes.isEmpty())
	{
		domElem = nodes.item(0).toElement();
		if (!domElem.isNull())
		{
			th = 0;
			list = domElem.text().split(';', QString::SkipEmptyParts);
			fw = list.size();
			thdr = new qint16* [fw];
			thcnt = new quint16 [fw];
			bzero(thdr, fw * sizeof(qint16*));
			for (i = 0; i < fw; i++)
			{
				list2 = list.at(i).split(',', QString::SkipEmptyParts);
				thdr[i] = new qint16[list2.size()];
				bzero(thdr[i], list2.size() * sizeof(qint16));
				thcnt[i] = list2.size();
				if (th < list2.size())
					th = list2.size();
				for (j = 0; j < list2.size(); j++)
				{
					thdr[i][j] = list2.at(j).toInt(&ok);
					checkOk;
				}
			}
		}
	}
	else
		setDeleting;
	colsRes = new QBitArray(fw);

	domElem = root.toElement();
	nodes = domElem.elementsByTagName("topheader");
	if (!nodes.isEmpty())
		domElem = nodes.item(0).toElement();
	else
		setDeleting;

	nodes = domElem.elementsByTagName("colors");
	if (!nodes.isEmpty())
	{
		domElem = nodes.item(0).toElement();
		if (!domElem.isNull())
		{
			list = domElem.text().split(';', QString::SkipEmptyParts);
			if (list.size() != fw)
				setDeleting;
			thcl = new qint16* [fw];
			bzero(thcl, fw * sizeof(qint16*));
			for (i = 0; i < fw; i++)
			{
				list2 = list.at(i).split(',', QString::SkipEmptyParts);
				if (list2.size() != getGroupCnt(true, i))
					setDeleting;
				thcl[i] = new qint16[list2.size()];
				bzero(thcl[i], list2.size() * sizeof(qint16));
				for (j = 0; j < list2.size(); j++)
				{
					thcl[i][j] = list2.at(j).toInt(&ok);
					checkOk;
				}
			}
		}
	}
	else
		setDeleting;

	domElem = root.toElement();

	/* let's find and read top header */
	nodes = domElem.elementsByTagName("leftheader");
	if (ver == "0.2")
	{
		if (!nodes.isEmpty())
			domElem = nodes.item(0).toElement();
		else
			setDeleting;

		nodes = domElem.elementsByTagName("values");
	}

	if (!nodes.isEmpty())
	{
		domElem = nodes.item(0).toElement();
		if (!domElem.isNull())
		{
			lw = 0;
			list = domElem.text().split(';', QString::SkipEmptyParts);
			fh = list.size();
			lhdr = new qint16* [fh];
			lhcnt = new quint16 [fh];
			bzero(lhdr, fh * sizeof(qint16*));
			for (i = 0; i < fh; i++)
			{
				list2 = list.at(i).split(',', QString::SkipEmptyParts);
				lhdr[i] = new qint16[list2.size()];
				bzero(lhdr[i], list2.size() * sizeof(qint16));
				lhcnt[i] = list2.size();
				if (lw < list2.size())
					lw = list2.size();
				for (j = 0; j < list2.size(); j++)
				{
					lhdr[i][j] = list2.at(j).toInt(&ok);
					checkOk;
				}
			}
		}
	}
	else
		setDeleting;

	domElem = root.toElement();
	nodes = domElem.elementsByTagName("leftheader");
	if (!nodes.isEmpty())
		domElem = nodes.item(0).toElement();
	else
		setDeleting;

	nodes = domElem.elementsByTagName("colors");
	if (!nodes.isEmpty())
	{
		domElem = nodes.item(0).toElement();
		if (!domElem.isNull())
		{
			list = domElem.text().split(';', QString::SkipEmptyParts);
			if (list.size() != fh)
				setDeleting;
			lhcl = new qint16* [fh];
			bzero(lhcl, fh * sizeof(qint16*));
			for (i = 0; i < fh; i++)
			{
				list2 = list.at(i).split(',', QString::SkipEmptyParts);
				if (list2.size() != getGroupCnt(false, i))
					setDeleting;
				lhcl[i] = new qint16[list2.size()];
				bzero(lhcl[i], list2.size() * sizeof(qint16));
				for (j = 0; j < list2.size(); j++)
				{
					lhcl[i][j] = list2.at(j).toInt(&ok);
					checkOk;
				}
			}
		}
	}
	else
		setDeleting;

	rowsRes = new QBitArray(fh);

	field = new CellState* [fw]; //создание двумерного динамического массива

	fieldColor = new quint16* [fw];
	bzero(field, fw * sizeof(CellState*));
	for (i = 0; i < fw; i++)
	{
		field[i] = new CellState[fh];
		bzero(field[i], fh * sizeof(CellState));
		fieldColor[i] = new quint16[fh];
		bzero(fieldColor[i], fh * sizeof(quint16));
	}

	fieldLayers = new CellState ** [colorMapCount]; //цветовые слои поля
	for (i = 0; i < colorMapCount; i++)
	{
		currLayer = i + 1;
		currBrushColor = i;

		fieldLayers[i] = new CellState * [fw]; //создание двумерного динамического массива
		for (j = 0; j < fw; j++)
		{
			fieldLayers[i][j] = new CellState[fh];
			bzero(fieldLayers[i][j], fh * sizeof(CellState));
		}
		for (j = 0; j < fw; j++)
		{
			bool found = false;
			for (k = 0; k < getGroupCnt(true, j); k++)
				if (thcl[j][k] == i)
				{
					found = true;
					break;
				}
			if (!found)
				for (k = 0; k < fh; k++)
					fieldLayers[i][j][k] = csEmpty;
		}
		for (j = 0; j < fh; j++)
		{
			bool found = false;
			for (k = 0; k < getGroupCnt(false, j); k++)
				if (lhcl[j][k] == i)
				{
					found = true;
					break;
				}
			if (!found)
				for (k = 0; k < fw; k++)
					fieldLayers[i][k][j] = csEmpty;
		}
	}

	currBrushColor = colorMapCount - 1;
	currLayer = currBrushColor + 1;

	for (i = 0; i < fw; i++)
		for (j = 0; j < fh; j++)
		{
			fX = i + lw;
			fY = j + th;
			changeCellState(fieldLayers[currBrushColor][i][j]);
		}

	currBrushColor = 0;
	currLayer = 0;

	/* ищем и читаем состояния клеток поля */
	nodes = root.elementsByTagName("field");
	if (!nodes.isEmpty())
	{
		domElem = nodes.item(0).toElement();
		if (!domElem.isNull())
		{
			nodes = domElem.elementsByTagName("cell");
			for (i = 0; i < nodes.length(); i++)
			{
				quint16 x = nodes.item(i).toElement().attribute("col").toUInt(&ok);
				checkOk;
				quint16 y = nodes.item(i).toElement().attribute("row").toUInt(&ok);
				checkOk;
				QString state = nodes.item(i).toElement().attribute("state");
				fX = x + lw;
				fY = y + th;
				quint16 col = nodes.item(i).toElement().attribute("color").toUInt(&ok);
				if (ok)
				{
					if (col > colorMapCount - 1)
						setDeleting;
					currLayer = col + 1;
					if (state == "filled")
					{
						if (field[x][y] == csFilled || field[x][y] == csEmpty)
							setDeleting;
						changeCellState(csFilled);
					}
					else if (state == "empty")
					{
						if (field[x][y] == csFilled || field[x][y] == csEmpty)
							setDeleting;
						changeCellState(csEmpty);
					}
					else
						setDeleting;
				}
				else
					if (state == "empty")
					{
						if (field[x][y] == csFilled)
							setDeleting;
						for (j = 0; j < colorMapCount; j++)
						{
							currLayer = j + 1;
							changeCellState(csEmpty);
						}
					}
			}
		}
		else
			setDeleting;
		currLayer = 0;
	}


	nodes = root.elementsByTagName("comment");
	if (!nodes.isEmpty())
	{
		domElem = nodes.item(0).toElement();
		if (!domElem.isNull())
			comment = domElem.text();
	}

	keyFillPressed = false;
	keyEmptyPressed = false;
	keyUndefPressed = false;
	fX = oldFX = lw;
	fY = oldFY = th;
	undoList.clear();
	redoList.clear();
	setMouseTracking(true);				// включаем отслеживание движения мыши
	setFocusPolicy(Qt::StrongFocus);
}

ColorCW::ColorCW(const quint16 width, const quint16 height, const quint16 topHeaderHeight, const quint16 leftHeaderWidth, QTime* time, QWidget* parent, Qt::WindowFlags f)
	: RectCrossword(CWType::Color, time, parent, f)
{
	newCrossword(CWType::FillUpHeaders, width, height, topHeaderHeight, leftHeaderWidth);
}

ColorCW::ColorCW(const quint16 width, const quint16 height, QTime* time, QWidget* parent, Qt::WindowFlags f)
	: RectCrossword(CWType::Color, time, parent, f)
{
	newCrossword(CWType::PaintCrossword, width, height, 0, 0);
}

void ColorCW::newCrossword(const CWType::CrosswordMode m, const quint16 fieldWidth, const quint16 fieldHeight, const quint16 topHeaderHeight, const quint16 leftHeaderWidth)
{
	quint16 i, j;

	mode = m;
	fw = fieldWidth;
	fh = fieldHeight;
	th = topHeaderHeight;
	lw = leftHeaderWidth;
	name = "";
	author = "";
	date = "";
	numCorrections = 0;
	this->time->setHMS(0, 0, 0); //?
	thdr = new qint16* [fw];
	lhdr = new qint16* [fh];
	thcnt = new quint16 [fw];
	lhcnt = new quint16 [fh];

	bzero(thdr, fw * sizeof(qint16*));
	bzero(lhdr, fh * sizeof(qint16*));

	for (i = 0; i < fw; i++)
	{
		thdr[i] = new qint16[th];
		thcnt[i] = th;
		for (j = 0; j < th; j++)
			thdr[i][j] = 0;
	}
	for (i = 0; i < fh; i++)
	{
		lhdr[i] = new qint16[lw];
		lhcnt[i] = lw;
		for (j = 0; j < lw; j++)
			lhdr[i][j] = 0;
	}

	rowsRes = new QBitArray(fh); //?

	field = new CellState* [fw]; //создание двумерного динамического массива
	bzero(field, fw * sizeof(CellState*));
	for (i = 0; i < fw; i++)
	{
		field[i] = new CellState[fh];
		bzero(field[i], fh * sizeof(CellState));
	}

	comment = "";

	keyFillPressed = false; //?
	keyEmptyPressed = false; //?
	keyUndefPressed = false; //?
	fX = oldFX = lw; //?
	fY = oldFY = th; //?
	editHeaderX = lw;
	editHeaderY = 0;
	editHeaderValue = 0;
	isEdit = false;
	undoList.clear();
	redoList.clear();
	setMouseTracking(true);	// включаем отслеживание движения мыши
	setFocusPolicy(Qt::StrongFocus); //?
}

ColorCW::~ColorCW()
{
	// ^^^ надо бы удалить всё, что мы тама создали
	quint16 i;
	if (rowsRes != NULL)
		delete rowsRes;
	if (lhdr != NULL)
	{
		for (i = 0; i < lw; i++)
			if (lhdr[i] != NULL)
				delete[] lhdr[i];
		delete[] lhdr;
	}
	if (colsRes != NULL)
		delete colsRes;
	if (thdr != NULL)
	{
		for (i = 0; i < fw; i++)
			if (thdr[i] != NULL)
				delete[] thdr[i];
		delete[] thdr;
	}
	if (field != NULL)
	{
		for (i = 0; i < fw; i++)
			if (field[i] != NULL)
				delete[] field[i];
		delete[] field;
	}
	undoList.clear();
	redoList.clear();
}

void ColorCW::paintEvent(QPaintEvent* /*event*/)
{
	QStylePainter painter(this);	//object for painting
	painter.drawPixmap(0, 0, pixmap);

	if (hasFocus())
	{
		QStyleOptionFocusRect option;
		option.initFrom(this);
		//option.backgroundColor = palette().light().color();
		painter.drawPrimitive(QStyle::PE_FrameFocusRect, option);
	}
}

bool ColorCW::calcHighlightXY(const QPoint& originPoint)
{
	bool changed = false;
	fX = (originPoint.x() - margin) / cellSize;					// координата клетки
	fY = (originPoint.y() - margin) / cellSize;					// на поле
	if ((fX < lw && fY < th) || (fX >= fw + lw) || (fY >= fh + th))
		//если выделенная клетка не находится в области поля или заголовков, восстанавливаем предыдущее значение
	{
		fX = oldFX;
		fY = oldFY;
	}
	else if (fX != oldFX || fY != oldFY)
	{
		changed = true;
		updatePixmap();
		oldFX = fX;
		oldFY = fY;
	}
	return changed;
}

void ColorCW::mouseMoveEvent(QMouseEvent* event)
{
	if (calcHighlightXY(event->pos()))
	{
		Qt::MouseButton button = Qt::NoButton;
		if (event->buttons().testFlag(Qt::LeftButton))			// если двигаем мышу, и
			button =  Qt::LeftButton;
		else if (event->buttons().testFlag(Qt::RightButton))	// нажата одна из кнопок
			button =  Qt::RightButton;
		else if (event->buttons().testFlag(Qt::MidButton))		// то генерим событие
			button =  Qt::MidButton;
		if (button != Qt::NoButton)								// нажатия кнопки
		{
			QMouseEvent* mouseEvent = new QMouseEvent(QEvent::MouseButtonPress, event->pos(),
					button, event->buttons(), event->modifiers());
			mousePressEvent(mouseEvent);
		}
	}
	event->accept();
}

void ColorCW::mousePressEvent(QMouseEvent* event)
{
	calcHighlightXY(event->pos());
	CellState newState;
	switch (event->button())
	{
		case Qt::LeftButton:
			newState = csFilled;
			if (mode == CWType::FillUpHeaders && (editHeaderX != fX || editHeaderY != fY))
			{
				editHeaderX = 0;
				editHeaderY = 0;
				editHeaderValue = 0;
				isEdit = false;

				if ((fX >= lw && fY < th) || (fX < lw && fY >= th))
				{
					editHeaderX = fX;
					editHeaderY = fY;
				}
			}
			break;
		case Qt::MidButton:
			newState = csUndef;
			break;
		case Qt::RightButton:
			newState = csEmpty;
			break;
	}
	if (mode != CWType::FillUpHeaders)
		changeCellState(newState);
	event->accept();
	updatePixmap();
}

void ColorCW::wheelEvent(QWheelEvent* event)
{
	if (event->modifiers().testFlag(Qt::ControlModifier))
	{									// если нажат Ctrl, то изменяем размер клетки
		quint16 d = qAbs(event->delta() / 120);
		if (event->delta() > 0)			// скроллинг вверх
			cellSize += d;
		else
			if (cellSize + d > MIN_CELLSIZE)
				cellSize -= d;
	}
	else if (event->modifiers().testFlag(Qt::ShiftModifier))
	{									// если нажат Shift, то включаем горизонтальный скроллинг
		QWheelEvent* ev = new QWheelEvent(event->pos(), event->delta(), event->buttons(),
				event->modifiers(), Qt::Horizontal);
		qApp->postEvent(parentWidget(), ev);
	}
	else
	{
		event->setAccepted(false);
		return;
	}
	updatePixmap();
	calcHighlightXY(event->pos());
	event->setAccepted(true);
	return;
}

#define checkPressedKeys \
		if (keyFillPressed) \
			changeCellState(csFilled); \
		else if (keyEmptyPressed) \
			changeCellState(csEmpty); \
		else if (keyUndefPressed) \
			changeCellState(csUndef);

void ColorCW::appendValue(QString val)
{
	if (mode == CWType::FillUpHeaders)
		setHeaderValue(QString::number(editHeaderValue).append(val).toUShort());
	isEdit = true;
}

void ColorCW::setHeaderValue(quint16 val)
{
	editHeaderValue = val;
	if (editHeaderY < th && editHeaderX >= lw)
		thdr[editHeaderX - lw][editHeaderY] = val;
	if (editHeaderX < lw && editHeaderY >= th)
		lhdr[editHeaderY - th][editHeaderX] = val;
	updatePixmap();
}

void ColorCW::keyPressEvent(QKeyEvent* event)
{
	switch (event->key())
	{
		case Qt::Key_Return:
		case Qt::Key_Enter:
			if (mode == CWType::FillUpHeaders && (editHeaderX > 0 || editHeaderY > 0))
			{
				if (editHeaderY < th)
					if (editHeaderY < th - 1)
						editHeaderY++;
					else if (editHeaderX < (lw + fw - 1))
					{
						editHeaderX++;
						editHeaderY = 0;
					}
					else
					{
						editHeaderX = 0;
						editHeaderY = th;
					}
				else if (editHeaderX < lw)
				{
					if (editHeaderX < lw - 1)
						editHeaderX++;
					else if (editHeaderY < (th + fh - 1))
					{
						editHeaderY++;
						editHeaderX = 0;
					}
					else
					{
						editHeaderX = lw;
						editHeaderY = 0;
					}
				}
				editHeaderValue = 0;
				isEdit = false;
				updatePixmap();
			}
			break;
		case Qt::Key_Up:
			if (mode == CWType::FillUpHeaders)
			{
				if ((editHeaderX >= lw && editHeaderY > 0) || (editHeaderY > th && editHeaderX < lw))
					editHeaderY--;
				editHeaderValue = 0;
				isEdit = false;
			}
			else
				if (fY > th || (fX > lw - 1 && fY > 0))
				{
					fY--;
					checkPressedKeys;
				}
			break;
		case Qt::Key_Down:
			if (mode == CWType::FillUpHeaders)
			{
				if ((editHeaderX >= lw && editHeaderY < th - 1) || (editHeaderY < th + fh - 1 && editHeaderX < lw))
					editHeaderY++;
				editHeaderValue = 0;
				isEdit = false;
			}
			else
				if (fY < fh + th - 1)
				{
					fY++;
					checkPressedKeys;
				}
			break;
		case Qt::Key_Left:
			if (mode == CWType::FillUpHeaders)
			{
				if ((editHeaderY >= th && editHeaderX > 0) || (editHeaderX > lw && editHeaderY < th))
					editHeaderX--;
				editHeaderValue = 0;
				isEdit = false;
			}
			else
				if (fX > lw || (fY > th - 1 && fX > 0))
				{
					fX--;
					checkPressedKeys;
				}
			break;
		case Qt::Key_Right:
			if (mode == CWType::FillUpHeaders)
			{
				if ((editHeaderY >= th && editHeaderX < lw - 1) || (editHeaderX < lw + fw - 1 && editHeaderY < th))
					editHeaderX++;
				editHeaderValue = 0;
				isEdit = false;
			}
			else
				if (fX < fw + lw - 1)
				{
					fX++;
					checkPressedKeys;
				}
			break;
		case Qt::Key_Tab: //works on Ctrl + Tab
			if (mode == CWType::FillUpHeaders)
			{
				if (editHeaderX >= lw && editHeaderY < th)
				{
					editHeaderX = 0;
					editHeaderY = th;
				}
				else if (editHeaderX < lw && editHeaderY >= th)
				{
					editHeaderX = lw;
					editHeaderY = 0;
				}
				editHeaderValue = 0;
				isEdit = false;
			}
			break;
		case Qt::Key_0:
			appendValue("0");
			break;
		case Qt::Key_1:
			appendValue("1");
			break;
		case Qt::Key_2:
			appendValue("2");
			break;
		case Qt::Key_3:
			appendValue("3");
			break;
		case Qt::Key_4:
			appendValue("4");
			break;
		case Qt::Key_5:
			appendValue("5");
			break;
		case Qt::Key_6:
			appendValue("6");
			break;
		case Qt::Key_7:
			appendValue("7");
			break;
		case Qt::Key_8:
			appendValue("8");
			break;
		case Qt::Key_9:
			appendValue("9");
			break;
		case Qt::Key_Delete:
			if (mode == CWType::FillUpHeaders && !isEdit)
			{
				setHeaderValue(0);
				isEdit = false;
			}
			break;
		case Qt::Key_Backspace:
			if (mode == CWType::FillUpHeaders)
			{
				if (QString::number(editHeaderValue).length() > 1)
					setHeaderValue(QString::number(editHeaderValue).left(QString::number(editHeaderValue).length() - 1).toUShort());
				else
					setHeaderValue(0);
				isEdit = true;
			}
			break;
		case Qt::Key_Z:									// Z -> filled
			changeCellState(csFilled);
			keyFillPressed = true;
			break;
		case Qt::Key_X:									// X -> empty
			changeCellState(csEmpty);
			keyEmptyPressed = true;
			break;
		case Qt::Key_C:									// C -> undefined
			changeCellState(csUndef);
			keyUndefPressed = true;
			break;
		case Qt::Key_Plus:								// + -> увеличить размер клетки
			cellSize++;
			break;
		case Qt::Key_Minus:								// - -> уменьшить размер клетки
			if (cellSize > MIN_CELLSIZE)
				cellSize--;
			break;
		default:
			QWidget::keyPressEvent(event);
			return;
	}
	if (mode == CWType::FillUpHeaders)
		emit checkHeaders();
	updatePixmap();
}

void ColorCW::keyReleaseEvent(QKeyEvent* event)
{
	switch (event->key())
	{
		case Qt::Key_Z:
			keyFillPressed = false;
			break;
		case Qt::Key_X:
			keyEmptyPressed = false;
			break;
		case Qt::Key_C:
			keyUndefPressed = false;
			break;
		default:
			QWidget::keyReleaseEvent(event);
			return;
	}
}

void ColorCW::changeCellState(CellState newState)
{
	if (isSolved)
		return;
	quint16 fieldX = fX - lw;
	quint16 fieldY = fY - th;

	qint16 i;
	if (fX >= lw && fX < fw + lw && fY >= th && fY < th + fh)	// если попали на поле
	{
		if (field[fieldX][fieldY] != csUndef && field[fieldX][fieldY] != newState && mode == CWType::SolvingCrossword)
			numCorrections++;

/*			redoList.clear();
		History step;
		step.coordX = fieldX;
		step.coordY = fieldY;
		step.state = field[fieldX][fieldY];
		undoList.append(step);*/

		if (currLayer > 0)
		{
			currBrushColor = currLayer - 1;
			fieldLayers[currBrushColor][fieldX][fieldY] = newState;
		}
		if (currLayer == 0 || newState == csFilled)
			for (i = 0; i < colorMapCount; i++)
				if (newState == csFilled)
					if (i != currBrushColor)
						fieldLayers[i][fieldX][fieldY] = csEmpty;
					else
						fieldLayers[i][fieldX][fieldY] = csFilled;
				else
					fieldLayers[i][fieldX][fieldY] = newState;
		fieldColor[fieldX][fieldY] = currBrushColor;

		quint16 emptyCellsSum = 0;
		field[fieldX][fieldY] = csUndef;
		for (i = 0; i < colorMapCount; i++)
			if (fieldLayers[i][fieldX][fieldY] == csFilled)
			{
				field[fieldX][fieldY] = csFilled;
				fieldColor[fieldX][fieldY] = i;
				break;
			}
			else if (fieldLayers[i][fieldX][fieldY] == csEmpty)
				emptyCellsSum++;
		if (emptyCellsSum == colorMapCount)
			field[fieldX][fieldY] = csEmpty;
		// надо запустить чекалку поля
		emit cellStateChanged(fieldX, fieldY);
	}
	else if (fX < lw && fY >= th && fY < fh + th)	// если попали в левый заголовок
	{
		if (currLayer == 0)
			lhdr[fieldY][fX - (lw - getGroupCnt(false, fieldY))] *= -1;
		else
		{
			quint16 pnt = lw - fX;
			bool isColor;
			for (i = getGroupCnt(false, fieldY) - 1; i >= 0; i--)
			{
				if (i == getGroupCnt(false, fieldY) - 1)
				{
					if (lhcl[fieldY][i] == currLayer - 1)
						isColor = false;
					else
						isColor = true;
				}
				if ((lhcl[fieldY][i] == currLayer - 1) || (lhcl[fieldY][i] != currLayer - 1 && isColor))
				{
					pnt--;
					isColor = (lhcl[fieldY][i] == currLayer - 1);
				}
				if (pnt == 0 && isColor)
				{
					lhdr[fieldY][i] *= -1;
					break;
				}
			}
		}
	}
	else if (fX >= lw && fX < lw + fw && fY < th)	// если попали в верхний заголовок
	{
		if (currLayer == 0)
			thdr[fieldX][fY - (th - getGroupCnt(true, fieldX))] *= -1;
		else
		{
			quint16 pnt = th - fY;
			bool isColor;
			for (i = getGroupCnt(true, fieldX) - 1; i >= 0; i--)
			{
				if (i == getGroupCnt(true, fieldX) - 1)
				{
					if (thcl[fieldX][i] == currLayer - 1)
						isColor = false;
					else
						isColor = true;
				}
				if ((thcl[fieldX][i] == currLayer - 1) || (thcl[fieldX][i] != currLayer - 1 && isColor))
				{
					pnt--;
					isColor = (thcl[fieldX][i] == currLayer - 1);
				}
				if (pnt == 0 && isColor)
				{
					thdr[fieldX][i] *= -1;
					break;
				}
			}
		}
	}
}

void ColorCW::clearField()
{
	if (isSolved)
		return;
	quint16 i, j, c;
	quint16 oldColor = currBrushColor;
	for (c = 0; c < colorMapCount; c++)
		for (i = 0; i < fw; i++)
		{
			setCurrentLayer(c + 1);
			for (j = 0; j < fh; j++)
			{
				fX = i + lw;
				fY = j + th;
				changeCellState(csUndef);
			}
		}
		for (i = 0; i < th; i++)
			for (j = 0; j < th; j++)
				thdr[i][j] = qAbs(thdr[i][j]);
		for (i = 0; i < lw; i++)
			for (j = 0; j < fh; j++)
				lhdr[i][j] = qAbs(lhdr[i][j]);
	setCurrentLayer(0);
	setPenColor(oldColor);
	numCorrections = 0;
	undoList.clear();
	redoList.clear();
	updatePixmap();
	emit cellStateChanged(quint16(-2), quint16(-2));
}

ColorCW::CellState** ColorCW::getField()
{
	return field;
}

void ColorCW::save()
{
	QDomDocument doc("crossword");
	QDomElement domElem = doc.createElement("crossword");

	/* записываем аттрибуты кроссворда: */
	domElem.setAttribute("type", "color");
	domElem.setAttribute("ver", "0.2");
	if (!name.isEmpty())
		domElem.setAttribute("name", name);
	if (!author.isEmpty())
		domElem.setAttribute("author", author);
	if (!date.isEmpty())
		domElem.setAttribute("date", date);
	if (!comment.isEmpty())
	{
		QDomElement elem = doc.createElement("comment");
		elem.appendChild(doc.createTextNode(comment));
		domElem.appendChild(elem);
	}
	if (mode == CWType::SolvingCrossword)
	{
		domElem.setAttribute("corr", numCorrections);
		if (time != NULL)
		{
			// вычисляем время решения в секундах:
			domElem.setAttribute("time", (time->hour() * 60 * 60) +
					(time->minute() * 60) + time->second());
		}
	}

	QDomElement elem, elem2, elemColor;
	QString text, textColor;

	quint16 i, j, layer;
	elem = doc.createElement("colormap");
	for (i = 0; i < colorMapCount; i++)
	{
		if (text.length() != 0)
			text.append(';');
		text.append(QString::number(colorMap[i].red) + QString(','));
		text.append(QString::number(colorMap[i].green) + QString(','));
		text.append(QString::number(colorMap[i].blue));
	}
	elem.appendChild(doc.createTextNode(text));
	domElem.appendChild(elem);

	/* let's save top header */
	elem = doc.createElement("topheader");
	elem2 = doc.createElement("values");
	elemColor = doc.createElement("colors");
	textColor.clear();
	text.clear();
	for (i = 0; i < fw; i++)
	{
		if (!(text.length() == 0 || text.endsWith(";")))
		{
			text.append(';');
			textColor.append(';');
		}
		if (mode != CWType::PaintCrossword)
			for (j = 0; j < ((mode == CWType::FillUpHeaders) ? (th) : (getGroupCnt(true, i))); j++)
			{
				if (thdr[i][j] == 0)
					continue;
				if (!(text.length() == 0 || text.endsWith(";")))
				{
					text.append(',');
					textColor.append(',');
				}
				text.append(QString::number(thdr[i][j]));
				textColor.append(QString::number(thcl[i][j]));
			}
		else
		{
			quint16 currGroup = 0;
			for (j = 0; j < fh; j++)
			{
				CellState currState = field[i][j];
				if (currState == csFilled && j < fh - 1)
					currGroup++;
				else
				{
					if (j == fh - 1 && currState == csFilled)
						currGroup++;
					if (currGroup != 0)
					{
						if (!(text.length() == 0 || text.endsWith(";")))
							text.append(',');
						text.append(QString::number(currGroup));
						currGroup = 0;
					}
				}
			}
		}
	}
	elem2.appendChild(doc.createTextNode(text));
	elemColor.appendChild(doc.createTextNode(textColor));
	elem.appendChild(elemColor);
	elem.appendChild(elem2);
	domElem.appendChild(elem);

	/* let's save left header */
	elem = doc.createElement("leftheader");
	elem2 = doc.createElement("values");
	elemColor = doc.createElement("colors");
	textColor.clear();
	text.clear();
	for (i = 0; i < fh; i++)
	{
		if (!(text.length() == 0 || text.endsWith(";")))
		{
			text.append(';');
			textColor.append(';');
		}
		if (mode != CWType::PaintCrossword)
			for (j = 0; j < ((mode == CWType::FillUpHeaders) ? (lw) : (getGroupCnt(false, i))); j++)
			{
				if (lhdr[i][j] == 0)
					continue;
				if (!(text.length() == 0 || text.endsWith(";")))
				{
					text.append(',');
					textColor.append(',');
				}
				text.append(QString::number(lhdr[i][j]));
				textColor.append(QString::number(lhcl[i][j]));
			}
		else
		{
			quint16 currGroup = 0;
			for (j = 0; j < fw; j++)
			{
				CellState currState = field[j][i];
				if (currState == csFilled && j < fw - 1)
					currGroup++;
				else
				{
					if (j == fw - 1 && currState == csFilled)
						currGroup++;
					if (currGroup != 0)
					{
						if (!(text.length() == 0 || text.endsWith(";")))
							text.append(',');
						text.append(QString::number(currGroup));
						currGroup = 0;
					}
				}
			}
		}
	}

	elem2.appendChild(doc.createTextNode(text));
	elemColor.appendChild(doc.createTextNode(textColor));
	elem.appendChild(elemColor);
	elem.appendChild(elem2);
	domElem.appendChild(elem);

	/* записываем состояния клеток поля, если надо: */
	bool needSave = false;
	for (i = 0; i < fw; i++)
		for (j = 0; j < fh; j++)
			if (field[i][j] != csUndef)
				needSave = true;
	if (mode == CWType::SolvingCrossword)
	{
		elem = doc.createElement("field");

		QBitArray cwColors(colorMapCount);
		for (i = 0; i < fw; i++)
			for (j = 0; j < fh; j++)
			{
				if (field[i][j] == csEmpty || field[i][j] == csFilled)
				{
					QDomElement cell = doc.createElement("cell");
					cell.setAttribute("col", i);
					cell.setAttribute("row", j);
					if (field[i][j] == csEmpty)
						cell.setAttribute("state", "empty");
					else
					{
						cell.setAttribute("state", "filled");
						cell.setAttribute("color", QString::number(fieldColor[i][j]));
					}
					elem.appendChild(cell);
				}
				else
					for (layer = 0; layer < colorMapCount; layer++)
						if (fieldLayers[layer][i][j] == csEmpty)
						{
							QDomElement cell = doc.createElement("cell");
							cell.setAttribute("col", i);
							cell.setAttribute("row", j);
							cell.setAttribute("state", "empty");
							cell.setAttribute("color", QString::number(layer));
							elem.appendChild(cell);
						}
			}
		domElem.appendChild(elem);
	}

	doc.appendChild(domElem);

	QString fileName = QFileDialog::getSaveFileName(this, tr("Save crossword"), NULL,
			tr("Crosswords (*.jcw);;All files(*)"));
	if (fileName == NULL)					// если ничё не выбрано, то выход
		return;

	if (fileName.right(4) != ".jcw")
		fileName.append(".jcw");

	QFile* file = new QFile(fileName);
	if (!file->open(QIODevice::WriteOnly))
	{
		QMessageBox::critical(this, tr("Error"), tr("Can't save to file"));
		return;
	}

	QTextStream(file) << doc.toString();
	file->close();
}

void ColorCW::updateProgress()
{
	emit cellStateChanged(quint16(-1), quint16(-1));
	updatePixmap();
}

void ColorCW::updatePixmap()
{
	QSize fieldSize((margin * 2) + (cellSize * (lw + fw)), (margin * 2) + (cellSize * (th + fh)));
	QSize parentSize = parentWidget()->size();
	resize(fieldSize.expandedTo(parentSize));

	pixmap = QPixmap(size());
	pixmap.fill(this, 0, 0);
	QPainter painter(&pixmap);
	painter.initFrom(this);

	QPen penNormal = painter.pen();			// перо рисования границ
	penNormal.setWidth(1);
	QPen penBold = painter.pen();			// перо рисования жирных границ
	penBold.setWidth(2);
	QPen greenPen;
	greenPen.setColor(Qt::green);
	QFont font = painter.font();
	font.setPointSize(cellSize * 0.7);		// установка размера шрифта в зависимости от размера клетки
	painter.setFont(font);

	qint16 i, j;
	quint16 middleColor;
	quint16 pointX = margin + lw * cellSize;	// координаты начальной точки поля
	quint16 pointY = margin + th * cellSize;
	painter.save();

	/* рисуем линии поля и цифры */
	if (mode != CWType::FillUpHeaders)
	{
		if (!(mode == CWType::SolvingCrossword && isSolved))
		{
			painter.setBrush(QColor(210, 210, 210));

			if (fX - lw >= 0)
				painter.drawRect(margin + fX * cellSize, margin, cellSize, cellSize * (th + fh));
			if (fY - th >= 0)
				painter.drawRect(margin, margin + fY * cellSize, cellSize * (lw + fw), cellSize);
		}
	}
	else
		if ((editHeaderX >= lw && editHeaderY < th) || (editHeaderX < lw && editHeaderY >= th))
		{
			if (isEdit)
				painter.setBrush(QColor(200, 255, 255));
			else
				painter.setBrush(QColor(Qt::yellow));
			painter.drawRect(margin + editHeaderX * cellSize, margin + editHeaderY * cellSize, cellSize, cellSize);
		}

	painter.restore();
	painter.save();
	painter.translate(pointX, pointY);
	painter.setBrush(Qt::SolidPattern);
	int pointRadius = cellSize * 0.1;
	for (i = 0; i < fw; i++)
		for (j = 0; j < fh; j++)
		{
			QPen oldPen = painter.pen();
			painter.setBrush(QColor(colorMap[fieldColor[i][j]].red, colorMap[fieldColor[i][j]].green, colorMap[fieldColor[i][j]].blue));
			if (mode != CWType::FillUpHeaders)
			{
				if ((field[i][j] == csFilled && currLayer == 0) || (currLayer > 0 && fieldLayers[currLayer - 1][i][j] == csFilled))
					painter.drawRect(i * cellSize, j * cellSize, cellSize, cellSize);
				else if (((field[i][j] == csEmpty && currLayer == 0) || (currLayer > 0 && fieldLayers[currLayer - 1][i][j] == csEmpty)) && mode != CWType::PaintCrossword)
					if (!(mode == CWType::SolvingCrossword && isSolved))
					{
						painter.setBrush(Qt::black);
						painter.drawEllipse((i + 0.5) * cellSize - pointRadius, (j + 0.5) * cellSize -
						 pointRadius, pointRadius * 2, pointRadius * 2);
					}
			}

			if (mode == CWType::SolvingCrossword && (colsRes->at(i) || rowsRes->at(j)))
			{
				painter.setBrush(Qt::black);
				painter.setPen(oldPen);
			}
		}
	painter.restore();

	quint16 bottomY = (fh + th) * cellSize;	// нижняя координата Y верхнего заголовка
	quint16 rigthX = fw * cellSize;			// правая координата X верхнего заголовка
	painter.save();
	painter.translate(pointX, margin);

	for (i = 0; i <= fw; i++)				// рисуем вертикальные линии
		if (i % 5 == 0 || i == fw)			// каждую 5 границу рисуем жирнее
		{
			painter.setPen(penBold);
			if (!isSolved || i == 0)
				painter.drawLine(i * cellSize, 0, i * cellSize, bottomY);
			else
				painter.drawLine(i * cellSize, 0, i * cellSize, th * cellSize);
			painter.setPen(penNormal);
		}
		else
			if (!isSolved || i == fw || i == 0)
				painter.drawLine(i * cellSize, 0, i * cellSize, bottomY);
			else
				painter.drawLine(i * cellSize, 0, i * cellSize, th * cellSize);

	painter.setPen(penBold);
	painter.drawLine(0, 0, rigthX, 0);
	painter.setPen(penNormal);
	for (i = 1; i < th; i++)				// рисуем горизонтальные линии
		painter.drawLine(0, i * cellSize, rigthX, i * cellSize);

	painter.save();

	quint16 pos, summ;
	for (i = 0; i < fw; i++)				//пишем цифры верхнего заголовка
	{
		pos = 1;
		summ = 0;
		for (j = getGroupCnt(true, i) - 1; j >= 0 ; j--)
			if (thdr[i][j] != 0)
			{
				if (currLayer > 0 && thcl[i][j] == currLayer - 1 && summ > 0)
				{
					painter.setPen(Qt::black);
					painter.drawText(i * cellSize, (th - pos) * cellSize, cellSize, cellSize, Qt::AlignCenter, QString::number(summ));
					pos++;
					summ = 0;
				}

				if (currLayer == 0)
				{
					painter.setBrush(QColor(colorMap[thcl[i][j]].red, colorMap[thcl[i][j]].green, colorMap[thcl[i][j]].blue));
					middleColor = (colorMap[thcl[i][j]].red + colorMap[thcl[i][j]].green + colorMap[thcl[i][j]].blue) / 3;
					if (middleColor < 127)
						middleColor = 255;
					else
						middleColor = 0;
					painter.setPen(QColor(middleColor, middleColor, middleColor));
					painter.drawRect(i * cellSize, (th - pos) * cellSize, cellSize, cellSize);
					painter.drawText(i * cellSize, (th - pos) * cellSize, cellSize, cellSize, Qt::AlignCenter, QString::number(qAbs(thdr[i][j])));
					if (thdr[i][j] < 0)
						painter.drawLine(i * cellSize, (th - pos) * cellSize,
								(i + 1) * cellSize, (th - pos + 1) * cellSize); //если цифра в заголовке отрицательная - перечёркиваем её в заголовке
					pos++;
				}
				else if (thcl[i][j] == currLayer - 1)
				{
					painter.setBrush(QColor(colorMap[thcl[i][j]].red, colorMap[thcl[i][j]].green, colorMap[thcl[i][j]].blue));
					middleColor = (colorMap[thcl[i][j]].red + colorMap[thcl[i][j]].green + colorMap[thcl[i][j]].blue) / 3;
					if (middleColor < 127)
						middleColor = 255;
					else
						middleColor = 0;
					painter.setPen(QColor(middleColor, middleColor, middleColor));
					painter.drawRect(i * cellSize, (th - pos) * cellSize, cellSize, cellSize);
					painter.drawText(i * cellSize, (th - pos) * cellSize, cellSize, cellSize, Qt::AlignCenter, QString::number(qAbs(thdr[i][j])));
					if (thdr[i][j] < 0)
						painter.drawLine(i * cellSize, (th - pos) * cellSize,
								(i + 1) * cellSize, (th - pos + 1) * cellSize); //если цифра в заголовке отрицательная - перечёркиваем её в заголовке
					pos++;
				}
				else
					summ += qAbs(thdr[i][j]);

				if (currLayer > 0 && j == 0 && summ > 0 && pos > 1)
				{
					painter.setPen(Qt::black);
					painter.drawText(i * cellSize, (th - pos) * cellSize, cellSize, cellSize, Qt::AlignCenter, QString::number(summ));
					pos++;
					summ = 0;
				}
			}
	}
	painter.restore();
	painter.restore();

	bottomY = fh * cellSize;
	rigthX = (fw + lw) * cellSize;
	painter.save();
	painter.translate(margin, pointY);

	for (i = 0; i <= fh; i++)				// рисуем горизонтальные линии
		if (i % 5 == 0 || i == fh)			// каждую 5 границу рисуем жирнее
		{
			painter.setPen(penBold);
			if (!isSolved || i == 0)
				painter.drawLine(0, i * cellSize, rigthX, i * cellSize);
			else
				painter.drawLine(0, i * cellSize, lw * cellSize, i * cellSize);
			painter.setPen(penNormal);
		}
		else
			if (!isSolved || i == fh || i == 0)
				painter.drawLine(0, i * cellSize, rigthX, i * cellSize);
			else
				painter.drawLine(0, i * cellSize, lw * cellSize, i * cellSize);

	painter.setPen(penBold);
	painter.drawLine(0, 0, 0, bottomY);
	painter.setPen(penNormal);
	for (i = 1; i < lw; i++)				// рисуем вертикальные линии
		painter.drawLine(i * cellSize, 0, i * cellSize, bottomY);

	painter.save();

	for (i = 0; i < fh; i++)				//пишем цифры левого заголовка
	{
		pos = 1;
		summ = 0;
		for (j = getGroupCnt(false, i) - 1; j >= 0 ; j--)
			if (lhdr[i][j] != 0)
			{
				if (currLayer > 0 && lhcl[i][j] == currLayer - 1 && summ > 0)
				{
					painter.setPen(Qt::black);
					painter.drawText((lw - pos) * cellSize, i * cellSize, cellSize, cellSize, Qt::AlignCenter, QString::number(summ));
					pos++;
					summ = 0;
				}

				if (currLayer == 0)
				{
					painter.setBrush(QColor(colorMap[lhcl[i][j]].red, colorMap[lhcl[i][j]].green, colorMap[lhcl[i][j]].blue));
					middleColor = (colorMap[lhcl[i][j]].red + colorMap[lhcl[i][j]].green + colorMap[lhcl[i][j]].blue) / 3;
					if (middleColor < 127)
						middleColor = 255;
					else
						middleColor = 0;
					painter.setPen(QColor(middleColor, middleColor, middleColor));
					painter.drawRect((lw - pos) * cellSize, i * cellSize, cellSize, cellSize);
					painter.drawText((lw - pos) * cellSize, i * cellSize, cellSize, cellSize, Qt::AlignCenter, QString::number(qAbs(lhdr[i][j])));
					if (lhdr[i][j] < 0)
						painter.drawLine((lw - pos) * cellSize, i * cellSize,
								(lw - pos + 1) * cellSize, (i + 1) * cellSize); //если цифра в заголовке отрицательная - перечёркиваем её в заголовке
					pos++;
				}
				else if (lhcl[i][j] == currLayer - 1)
				{
					painter.setBrush(QColor(colorMap[lhcl[i][j]].red, colorMap[lhcl[i][j]].green, colorMap[lhcl[i][j]].blue));
					middleColor = (colorMap[lhcl[i][j]].red + colorMap[lhcl[i][j]].green + colorMap[lhcl[i][j]].blue) / 3;
					if (middleColor < 127)
						middleColor = 255;
					else
						middleColor = 0;
					painter.setPen(QColor(middleColor, middleColor, middleColor));
					painter.drawRect((lw - pos) * cellSize, i * cellSize, cellSize, cellSize);
					painter.drawText((lw - pos) * cellSize, i * cellSize, cellSize, cellSize, Qt::AlignCenter, QString::number(qAbs(lhdr[i][j])));
					if (lhdr[i][j] < 0)
						painter.drawLine((lw - pos) * cellSize, i * cellSize,
								(lw - pos + 1) * cellSize, (i + 1) * cellSize); //если цифра в заголовке отрицательная - перечёркиваем её в заголовке
					pos++;
				}
				else
					summ += qAbs(lhdr[i][j]);

				if (currLayer > 0 && j == 0 && summ > 0 && pos > 1)
				{
					painter.setPen(Qt::black);
					painter.drawText((lw - pos) * cellSize, i * cellSize, cellSize, cellSize, Qt::AlignCenter, QString::number(summ));
					pos++;
					summ = 0;
				}
			}
	}
	painter.restore();
	painter.restore();

	/* рисуем размеры поля */
	font.setPointSize(cellSize * 1.2);
	painter.setFont(font);
	painter.drawText(margin, margin, lw * cellSize, th * cellSize, Qt::AlignCenter,
			QString("%1x%2").arg(fw).arg(fh));

	update();
}

void ColorCW::setField(quint16 x, quint16 y, CellState st, bool isCol, QBitArray * c, QBitArray * r, bool * notToSetBit)
{
	CellState currState = (isCol) ? field[x][y] : field[y][x];
	if (currState != st)
	{
		if (isCol)
		{
			fX = x + lw;
			fY = y + th;
			r->setBit(y, true);
		}
		else
		{
			fX = y + lw;
			fY = x + th;
			c->setBit(y, true);
		}
		changeCellState(st);
		(*notToSetBit) = true;
		updatePixmap();
	}
}

void ColorCW::undo()
{
/*	if (undoList.count() == 0 || isSolved)
		return;

	History undoStep = undoList.takeLast();
	History redoStep = undoStep;
	redoStep.state = field[undoStep.coordX][undoStep.coordY];
	field[undoStep.coordX][undoStep.coordY] = undoStep.state;
	redoList.append(redoStep);
	updatePixmap();*/
}

void ColorCW::redo()
{
/*	if (redoList.count() == 0 || isSolved)
		return;

	History redoStep = redoList.takeLast();
	History undoStep = redoStep;
	undoStep.state = field[redoStep.coordX][redoStep.coordY];
	field[redoStep.coordX][redoStep.coordY] = redoStep.state;
	undoList.append(undoStep);
	updatePixmap();*/
}

void ColorCW::solved()
{
	isSolved = true;
	undoList.clear();
	redoList.clear();
}

void ColorCW::setPenColor(quint16 n)
{
	currBrushColor = n;
}

bool ColorCW::solve()
{
	qDebug() << "Ready";
	return true;
}

void ColorCW::setFieldLayer(quint16 x, quint16 y, CellState st, quint16 color, bool isCol, QBitArray * c, QBitArray * r, bool * notToSetBit)
{
	CellState currState = (isCol) ? fieldLayers[color][x][y] : fieldLayers[color][y][x];
	quint16 currColor = (isCol) ? fieldColor[x][y] : fieldColor[y][x];
	if (currState != st || (currState == st && currState == csFilled && currColor != color))
	{
		if (isCol)
		{
			fX = x + lw;
			fY = y + th;
			r->setBit(y, true);
		}
		else
		{
			fX = y + lw;
			fY = x + th;
			c->setBit(y, true);
		}
		setCurrentLayer(color + 1);
		changeCellState(st);
		(*notToSetBit) = true;
		updatePixmap();
	}
}

void ColorCW::setCurrentLayer(quint16 n)
{
	currLayer = n;
	if (n > 0)
		currBrushColor = n - 1;
	updatePixmap();
}
